// Package repository provides settlement order and detail persistence.
package repository

import (
	"context"

	"github.com/we-pay-kit/we-pay-kit/internal/db"
)

type SettlementOrder struct {
	ID                     int64
	SettlementNo           string
	SettlementPeriod       string
	TotalAmount            float64
	ServiceFeeRate         float64
	ServiceFeeAmount       float64
	ActualSettlementAmount float64
	SettlementType         string
	Status                 string
}

type SettlementDetail struct {
	ID               int64
	SettlementID     int64
	ActivityID       int64
	ActivityName     string
	TransactionCount int
	TotalAmount      float64
	DiscountAmount   float64
}

type SettlementRepository struct{ db *db.DB }

func NewSettlementRepository(database *db.DB) *SettlementRepository {
	return &SettlementRepository{db: database}
}

func (r *SettlementRepository) CreateOrder(ctx context.Context, o *SettlementOrder) (int64, error) {
	q := `INSERT INTO settlement_order(settlement_no, settlement_period, total_amount, service_fee_rate, service_fee_amount, actual_settlement_amount, settlement_type, status)
          VALUES($1,$2,$3,$4,$5,$6,$7,$8) RETURNING id`
	var id int64
	err := r.db.QueryRowContext(ctx, q, o.SettlementNo, o.SettlementPeriod, o.TotalAmount, o.ServiceFeeRate, o.ServiceFeeAmount, o.ActualSettlementAmount, o.SettlementType, o.Status).Scan(&id)
	return id, err
}

func (r *SettlementRepository) AddDetail(ctx context.Context, d *SettlementDetail) (int64, error) {
	q := `INSERT INTO settlement_detail(settlement_id, activity_id, activity_name, transaction_count, total_amount, discount_amount)
          VALUES($1,$2,$3,$4,$5,$6) RETURNING id`
	var id int64
	err := r.db.QueryRowContext(ctx, q, d.SettlementID, d.ActivityID, d.ActivityName, d.TransactionCount, d.TotalAmount, d.DiscountAmount).Scan(&id)
	return id, err
}

func (r *SettlementRepository) UpdateStatus(ctx context.Context, settlementNo, status string) error {
	q := `UPDATE settlement_order SET status=$1 WHERE settlement_no=$2`
	_, err := r.db.ExecContext(ctx, q, status, settlementNo)
	return err
}

func (r *SettlementRepository) GetByNo(ctx context.Context, settlementNo string) (*SettlementOrder, error) {
	q := `SELECT id, settlement_no, settlement_period, total_amount, service_fee_rate, service_fee_amount, actual_settlement_amount, settlement_type, status FROM settlement_order WHERE settlement_no=$1`
	row := r.db.QueryRowContext(ctx, q, settlementNo)
	var o SettlementOrder
	if err := row.Scan(&o.ID, &o.SettlementNo, &o.SettlementPeriod, &o.TotalAmount, &o.ServiceFeeRate, &o.ServiceFeeAmount, &o.ActualSettlementAmount, &o.SettlementType, &o.Status); err != nil {
		return nil, err
	}
	return &o, nil
}

func (r *SettlementRepository) ListOrders(ctx context.Context, limit, offset int) ([]SettlementOrder, error) {
	if limit <= 0 {
		limit = 20
	}
	q := `SELECT id, settlement_no, settlement_period, total_amount, service_fee_rate, service_fee_amount, actual_settlement_amount, settlement_type, status FROM settlement_order ORDER BY id DESC LIMIT $1 OFFSET $2`
	rows, err := r.db.QueryContext(ctx, q, limit, offset)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	res := make([]SettlementOrder, 0, limit)
	for rows.Next() {
		var o SettlementOrder
		if err := rows.Scan(&o.ID, &o.SettlementNo, &o.SettlementPeriod, &o.TotalAmount, &o.ServiceFeeRate, &o.ServiceFeeAmount, &o.ActualSettlementAmount, &o.SettlementType, &o.Status); err != nil {
			return nil, err
		}
		res = append(res, o)
	}
	return res, rows.Err()
}

func (r *SettlementRepository) ListDetailsBySettlement(ctx context.Context, settlementID int64, limit, offset int) ([]SettlementDetail, error) {
	if limit <= 0 {
		limit = 50
	}
	q := `SELECT id, settlement_id, activity_id, activity_name, transaction_count, total_amount, discount_amount FROM settlement_detail WHERE settlement_id=$1 ORDER BY id ASC LIMIT $2 OFFSET $3`
	rows, err := r.db.QueryContext(ctx, q, settlementID, limit, offset)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	res := make([]SettlementDetail, 0, limit)
	for rows.Next() {
		var d SettlementDetail
		if err := rows.Scan(&d.ID, &d.SettlementID, &d.ActivityID, &d.ActivityName, &d.TransactionCount, &d.TotalAmount, &d.DiscountAmount); err != nil {
			return nil, err
		}
		res = append(res, d)
	}
	return res, rows.Err()
}
